import {
  AppMobChartProps,
  ICtrlEventParam,
  IMobChartCtrlController,
  IParam,
  LogUtil,
  MobChartCtrlController,
  MobChartEvents,
  Util,
} from 'ibz-core';
import {
  IPSAppCodeList,
  IPSChartSeriesCSCartesian2DEncode,
  IPSChartSeriesCSNoneEncode,
  IPSChartXAxis,
  IPSChartYAxis,
  IPSCodeItem,
  IPSDEChartGrid,
  IPSDEChartSeries,
  IPSDEChartTitle,
} from '@ibiz/dynamic-model-api';
import {
  ChartBarSeriesController,
  ChartCandlestickSeriesController,
  ChartFunnelSeriesController,
  ChartGaugeSeriesController,
  ChartLineSeriesController,
  ChartMapSeriesController,
  ChartPieSeriesController,
  ChartRadarSeriesController,
  ChartScatterSeriesController,
} from 'ibz-core';
import { GenerateComponent } from '../component-base';
import { MDCtrlComponentBase } from './md-ctrl-component-base';
import { shallowReactive } from 'vue';
import { init } from 'echarts/lib/echarts';
import moment from 'moment';
/**
 * 图表部件
 *
 * @export
 * @class AppMobChart
 * @extends {MDCtrlComponentBase}
 */
export class AppMobChart extends MDCtrlComponentBase<AppMobChartProps> {
  /**
   * @description 图表部件控制器
   * @protected
   * @type {IMobChartCtrlController}
   * @memberof AppMobChart
   */
  protected c!: IMobChartCtrlController;

  /**
   * @description 设置响应式
   * @memberof AppMobChart
   */
  setup() {
    this.c = shallowReactive<MobChartCtrlController>(this.getCtrlControllerByType('CHART') as MobChartCtrlController);
    super.setup();
  }

  /**
   * @description 部件基础数据初始化
   * @memberof MobChartCtrlController
   */
  public init() {
    super.init();
    this.initSeriesModel();
    this.initChartOption();
    this.initChartUserParams();
  }

  /**
   * @description 执行部件事件
   * @param {ICtrlEventParam} arg 事件参数
   * @memberof AppMobMap
   */
  public emitCtrlEvent(arg: ICtrlEventParam) {
    this.ctx.emit('ctrlEvent', arg);
    if (arg.action == MobChartEvents.LOAD_SUCCESS) {
      const { data } = arg;
      this.transformToBasicChartSetData(data.data, () => {
        this.drawCharts();
      });
    }
  }

  /**
   * @description 初始化序列模型
   * @private
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private async initSeriesModel() {
    if (!this.c.controlInstance.getPSDEChartSerieses()) {
      return;
    }
    for (let index = 0; index < (this.c.controlInstance.getPSDEChartSerieses() as any)?.length; index++) {
      const series: IPSDEChartSeries = (this.c.controlInstance.getPSDEChartSerieses() as any)[index];
      if (series) {
        this.initChartSeries(await this.getSeriesModelParam(series), series);
      }
    }
  }

  /**
   * @description 填充序列模型数据
   * @private
   * @param {*} opts 序列参数
   * @param {*} series 序列
   * @memberof MobChartCtrlController
   */
  private initChartSeries(opts: any, series: any): void {
    switch (series.eChartsType) {
      // 折线图
      case 'line':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartLineSeriesController(opts);
        break;
      // 漏斗图
      case 'funnel':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartFunnelSeriesController(opts);
        break;
      // 饼图
      case 'pie':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartPieSeriesController(opts);
        break;
      // 柱状图
      case 'bar':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartBarSeriesController(opts);
        break;
      // 雷达图
      case 'radar':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartRadarSeriesController(opts);
        break;
      // 散点图
      case 'scatter':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartScatterSeriesController(opts);
        break;
      // 仪表盘
      case 'gauge':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartGaugeSeriesController(opts);
        break;
      // K线图
      case 'candlestick':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartCandlestickSeriesController(opts);
        break;
      // 自定义（暂时地图）
      case 'custom':
        this.c.seriesModel[series.name?.toLowerCase()] = new ChartMapSeriesController(opts);
        break;
    }
  }

  /**
   * @description 初始化图表参数
   * @private
   * @memberof MobChartCtrlController
   */
  private initChartOption() {
    const series: any = [];
    // 填充series
    const indicator: any = [];
    this.c.controlInstance.getPSDEChartSerieses()?.forEach((_series: IPSDEChartSeries) => {
      series.push(this.fillSeries(_series, indicator));
    });
    // 填充xAxis
    const xAxis: any = [];
    (this.c.controlInstance as any).getPSChartXAxises()?.forEach((_xAxis: IPSChartXAxis) => {
      xAxis.push(this.fillAxis(_xAxis));
    });
    // 填充yAxis
    const yAxis: any = [];
    (this.c.controlInstance as any).getPSChartYAxises()?.forEach((_yAxis: IPSChartYAxis) => {
      yAxis.push(this.fillAxis(_yAxis));
    });
    // 填充grid
    const grid: any = [];
    (this.c.controlInstance as any).getPSChartGrids()?.forEach((_grid: IPSDEChartGrid) => {
      grid.push({
        ...(_grid.baseOptionJOString ? new Function('return {' + _grid.baseOptionJOString + '}')() : {}),
      });
    });
    // chartOption参数
    const opt = {
      tooltip: { show: true },
      dataset: [],
      series: series,
      xAxis: xAxis,
      yAxis: yAxis,
      // grid: grid,
    };
    this.fillTitleOption(opt);
    this.fillLegendOption(opt);
    this.registerMap();
    // 合并chartOption
    Object.assign(this.c.chartOption, opt);
    // 雷达图特殊参数
    Object.assign(this.c.chartOption, { radar: { indicator } });
  }

  /**
   * @description 初始化图表用户自定义参数
   * @private
   * @memberof MobChartCtrlController
   */
  private initChartUserParams() {
    this.fillUserParam(this.c.controlInstance, this.c.chartUserParams, 'EC');
  }

  /**
   * @description 获取序列模型参数
   * @private
   * @param {*} series 序列
   * @return {*}  {Promise<IParam>}
   * @memberof MobChartCtrlController
   */
  private getSeriesModelParam(series: any): Promise<IParam> {
    const seriesValueField = series.valueField?.toLowerCase();
    const seriesCatalogField = series.catalogField?.toLowerCase();
    // 构造dataSetFields属性
    const opts: any = {
      name: series.name?.toLowerCase(),
      categorField: seriesCatalogField,
      valueField: seriesValueField,
      seriesValues: [],
      seriesIndex: series.index | 0,
      data: [],
      seriesMap: {},
      categorCodeList: {
        type: series.getCatalogPSCodeList()?.codeListType,
        tag: series.getCatalogPSCodeList()?.codeName,
        emptycode: 'empty',
        emptytext: series.getCatalogPSCodeList()?.emptyText,
      },
      dataSetFields: this.getDataSetFields(series),
      ecxObject: {
        label: {
          show: true,
          position: 'top',
        },
        labelLine: {
          length: 10,
          lineStyle: {
            width: 1,
            type: 'solid',
          },
        },
        itemStyle: {
          borderWidth: 1,
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 20,
          },
        },
      },
      seriesCodeList: series.getSeriesPSCodeList()
        ? {
            type: series.getSeriesPSCodeList()?.codeListType,
            tag: series.getSeriesPSCodeList()?.codeName,
            emptycode: 'empty',
            emptytext: series.getSeriesPSCodeList()?.emptyText,
          }
        : null,
      seriesNameField: series.seriesField?.toLowerCase(),
      ecObject: {},
      seriesTemp: {
        type: series.eChartsType,
      },
      type: series.eChartsType,
      seriesLayoutBy: series.seriesLayoutBy,
      baseOption: {},
    };
    // 饼图引导线默认配置
    if (Object.is(series.eChartsType, 'pie')) {
      Object.assign(opts.ecxObject.label, {
        position: 'outside',
        formatter: `{b}: {d}%({@${opts.valueField}})`,
      });
      Object.assign(opts.ecxObject.labelLine, {
        show: true,
      });
    }
    // 漏斗图默认配置
    if (Object.is(series.eChartsType, 'funnel')) {
      Object.assign(opts.ecxObject.label, {
        position: 'outside',
        formatter: `{b}: {d}%({@${opts.valueField}})`,
      });
    }
    // 地图默认配置（暂时自定义）
    if (Object.is(series.eChartsType, 'custom')) {
      Object.assign(opts.ecxObject.label, {
        formatter: `{b}: {@${opts.valueField}}`,
      });
      opts.ecxObject.tooltip = {
        trigger: 'item',
        formatter: '{b}:  {c}',
      };
    }
    // 处理自定义ECX参数
    this.fillUserParam(series, opts.ecxObject, 'ECX');
    this.fillUserParam(series, opts.ecObject, 'EC');
    Object.assign(opts, series.baseOptionJOString ? new Function('return {' + series.baseOptionJOString + '}')() : {});
    return opts;
  }

  /**
   * @description 获取序列dataset属性
   * @private
   * @param {*} series 序列
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private getDataSetFields(series: any) {
    const seriesData: any = [];
    const dataSet =
      (this.c.controlInstance as any).getPSChartDataSets()?.find((item: any) => {
        return item.id === series?.M?.getPSChartDataSet?.id || null;
      }) || null;
    if (!dataSet && !dataSet.getPSChartDataSetFields()) {
      return null;
    }
    for (let index = 0; index < dataSet.getPSChartDataSetFields()?.length; index++) {
      const dataFile: any = dataSet.getPSChartDataSetFields()[index];
      const data: any = {};
      if (dataFile.getPSCodeList()) {
        const codelist = dataFile.getPSCodeList();
        Object.assign(data, { codelist: codelist });
      }
      data['isGroupField'] = dataFile.groupField;
      data['name'] = dataFile.name?.toLowerCase();
      data['groupMode'] = dataFile.groupMode ? dataFile.groupMode : '';
      // 只读不合并数据（扩展值属性4）
      if (series.extValue4Field && Object.is(dataFile.name, series.extValue4Field)) {
        data['isReadOnly'] = true;
      }
      seriesData.push(data);
    }
    return seriesData;
  }

  /**
   * @description 填充标题配置
   * @private
   * @param {*} opts 图表参数
   * @memberof MobChartCtrlController
   */
  private fillTitleOption(opts: any) {
    if (this.c.controlInstance.getPSDEChartTitle()) {
      const _titleModel: IPSDEChartTitle | null = this.c.controlInstance.getPSDEChartTitle();
      const title: any = {
        show: _titleModel?.showTitle,
        text: this.$tl(_titleModel?.getTitlePSLanguageRes()?.lanResTag, _titleModel?.title),
        subtext: this.$tl(_titleModel?.getSubTitlePSLanguageRes()?.lanResTag, _titleModel?.subTitle),
      };
      if (_titleModel?.titlePos) {
        switch (_titleModel?.titlePos) {
          case 'LEFT':
            Object.assign(title, {
              left: 'left',
            });
            break;
          case 'RIGHT':
            Object.assign(title, {
              left: 'right',
            });
            break;
          case 'BOTTOM':
            Object.assign(title, {
              left: 'center',
              top: 'bottom',
            });
            break;
        }
      }
      Object.assign(opts, { title });
    }
  }

  /**
   * @description 填充图例配置
   * @private
   * @param {*} opts 图表参数
   * @memberof MobChartCtrlController
   */
  private fillLegendOption(opts: any) {
    const legendModel: any = this.c.controlInstance.getPSDEChartLegend();
    const legend: any = {
      show: legendModel?.showLegend,
    };
    if (legendModel?.legendPos) {
      switch (legendModel.legendPos) {
        case 'LEFT':
          Object.assign(legend, {
            left: 'left',
            top: 'middle',
            orient: 'vertical',
          });
          break;
        case 'RIGHT':
          Object.assign(legend, {
            left: 'right',
            top: 'middle',
            orient: 'vertical',
          });
          break;
        case 'BOTTOM':
          Object.assign(legend, {
            top: 'bottom',
          });
          break;
      }
    }
    Object.assign(opts, { legend });
  }

  /**
   * @description 注册地图
   * @private
   * @memberof MobChartCtrlController
   */
  private registerMap() {
    // TODO 地图暂时不支持
    // const userParams: any = this.c.controlInstance.userParams || {};
    // if (userParams?.mapName) {
    //     const geoJson = require(`@/assets/json/map/${userParams?.mapName}.json`);
    //     registerMap(userParams?.mapName, geoJson);
    // }
  }

  /**
   * @description 处理用户自定义参数
   * @private
   * @param {*} param 用户参数
   * @param {*} opts 绘制参数
   * @param {string} tag 标识
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private fillUserParam(param: any, opts: any, tag: string) {
    if (!param.userParams) {
      return;
    }
    const userParam = param.userParams;
    switch (tag) {
      case 'ECX':
        if (userParam['ECX.label']) {
          opts['label'] = eval('(' + userParam['ECX.label'] + ')');
        }
        if (userParam['ECX.labelLine']) {
          opts['labelLine'] = eval('(' + userParam['ECX.labelLine'] + ')');
        }
        if (userParam['ECX.itemStyle']) {
          opts['itemStyle'] = eval('(' + userParam['ECX.itemStyle'] + ')');
        }
        if (userParam['ECX.emphasis']) {
          opts['emphasis'] = eval('(' + userParam['ECX.emphasis'] + ')');
        }
        for (const key in userParam) {
          if (Object.prototype.hasOwnProperty.call(userParam, key)) {
            if (key.indexOf('EC.') != -1) {
              const value = userParam[key].trim();
              opts[key.replace('EC.', '')] = value;
            }
          }
        }
        break;
      case 'EC':
        for (const key in userParam) {
          if (Object.prototype.hasOwnProperty.call(userParam, key)) {
            if (key.indexOf('EC.') != -1) {
              const value = userParam[key].trim();
              opts[key.replace('EC.', '')] = this.isJson(value)
                ? this.deepJsonParseFun(JSON.parse(value))
                : this.isArray(value)
                ? eval(value)
                : value;
            }
          }
        }
        break;
      default:
        break;
    }
  }

  /**
   * @description 填充序列
   * @private
   * @param {*} series 序列
   * @param {*} [indicator=[]] 雷达图参数
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private fillSeries(series: any, indicator: any = []) {
    const encode: any = {};
    let customType: string = '';
    const assginCodeList = (codeList: any) => {
      codeList.getPSCodeItems?.()?.forEach((_item: IPSCodeItem) => {
        const item: any = {
          name: _item.text,
          max: _item.userParams?.MAXVALUE ? _item.userParams.MAXVALUE : null,
        };
        indicator.push(item);
        if ((_item?.getPSCodeItems?.() as any)?.length > 0) {
          assginCodeList(_item);
        }
      });
    };
    switch (series.eChartsType) {
      case 'line':
      case 'bar':
        const cSCartesian2DEncode = series.getPSChartSeriesEncode() as IPSChartSeriesCSCartesian2DEncode;
        encode.x = this.arrayToLowerCase(cSCartesian2DEncode.getX());
        encode.y = this.arrayToLowerCase(cSCartesian2DEncode.getY());
        break;
      case 'pie':
      case 'funnel':
        const CSNoneEncode = series.getPSChartSeriesEncode() as IPSChartSeriesCSNoneEncode;
        encode.itemName = CSNoneEncode.category?.toLowerCase();
        encode.value = CSNoneEncode.value?.toLowerCase();
        break;
      case 'radar':
        encode.itemName = 'type';
        const catalogCodeList = series.getCatalogPSCodeList?.() as IPSAppCodeList;
        if (catalogCodeList) {
          assginCodeList(catalogCodeList);
        }
        break;
      case 'scatter':
        break;
      case 'gauge':
        break;
      case 'candlestick':
        const candlestickEncode = series.getPSChartSeriesEncode() as IPSChartSeriesCSCartesian2DEncode;
        encode.x = this.arrayToLowerCase(candlestickEncode.getX());
        encode.y = this.arrayToLowerCase(candlestickEncode.getY());
        break;
      case 'custom':
        customType = 'map';
        break;
      default:
        break;
    }
    return {
      id: series?.name?.toLowerCase(),
      name: series.caption,
      type: customType ? customType : series.eChartsType,
      xAxisIndex: series?.getPSChartSeriesEncode()?.M?.getPSChartXAxis?.id | 0,
      yAxisIndex: series?.getPSChartSeriesEncode()?.M?.getPSChartYAxis?.id | 0,
      datasetIndex: series?.M?.getPSChartDataSet?.id | 0,
      encode: Object.keys(encode).length > 0 ? encode : null,
      ...(series.baseOptionJOString ? new Function('return {' + series.baseOptionJOString + '}')() : {}),
    };
  }

  /**
   * @description 填充坐标
   * @private
   * @param {*} axis 坐标
   * @return {*}  {IParam}
   * @memberof MobChartCtrlController
   */
  private fillAxis(axis: any): IParam {
    const _axis: any = {
      // gridIndex: axis.index,
      position: axis.position,
      type: axis.eChartsType,
      name: axis.caption,
    };
    const dataShowMode = (axis as any).dataShowMode;
    if (dataShowMode === 1) {
      //  纵向显示
      Object.assign(_axis, {
        axisLabel: {
          formatter: (value: any) => {
            if (value.length > 4) {
              return value.substr(0, 4).split('').join('\n') + '\n...';
            } else {
              return value.split('').join('\n');
            }
          },
        },
      });
    } else if (dataShowMode === 2) {
      //  横向显示
    } else if (dataShowMode === 3) {
      //  斜向显示
      Object.assign(_axis, {
        axisLabel: {
          rotate: 45,
          formatter: (value: any) => {
            if (value.length > 4) {
              return value.substr(0, 4) + '...';
            } else {
              return value;
            }
          },
        },
      });
    }
    // 填充用户自定义参数
    this.fillUserParam(axis, _axis, 'EC');
    if (axis.minValue) {
      _axis['min'] = axis.minValue;
    }
    if (axis.maxValue) {
      _axis['max'] = axis.maxValue;
    }
    return _axis;
  }

  /**
   * @description 绘制图表
   * @private
   * @memberof MobChartCtrlController
   */
  private drawCharts() {
    if (!this.c.myChart) {
      const element: any = document.getElementById(this.c.chartId);
      if (element) {
        this.c.myChart = init(element);
      }
    }
    //判断刷新时dom是否存在
    if (!Object.is(this.c.myChart._dom.offsetHeight, 0) && !Object.is(this.c.myChart._dom.offsetWidth, 0)) {
      const _chartOption = this.handleChartOPtion();
      this.c.chartRenderOption = { ..._chartOption };
      if (this.c.myChart) {
        this.c.myChart.setOption(_chartOption);
        this.onChartEvents();
        this.handleDefaultSelect();
        this.c.myChart.resize();
      }
    }
  }

  /**
   * @description 图标事件
   * @memberof MobChartCtrlController
   */
  public onChartEvents() {
    this.c.myChart.on('click', (e: any) => {
      this.onChartClick(e);
    });
    this.c.myChart.on('selectchanged', (e: any) => {
      if (this.c.isSelectFirstDefault) {
        if (e && e.fromActionPayload) {
          const _event = {
            seriesId: e.fromActionPayload.seriesId,
            data: e.fromActionPayload.curData,
            name: e.fromActionPayload.seriesId,
          };
          this.onChartClick(_event);
        }
      }
    });
  }

  /**
   * @description 处理默认选中
   * @private
   * @memberof MobChartCtrlController
   */
  private handleDefaultSelect() {
    if (this.c.isSelectFirstDefault) {
      const options = this.handleChartOPtion();
      const selectSeriesId = this.c.controlInstance.getPSDEChartSerieses()?.[0]?.name || null;
      const curData = options?.dataset[0]?.source?.[0] || undefined;
      if (selectSeriesId && curData) {
        this.c.myChart.dispatchAction({
          type: 'select',
          seriesId: selectSeriesId.toLowerCase(),
          dataIndex: 0,
          curData: curData,
        });
      }
    }
  }

  /**
   * @description 图表单击事件
   * @private
   * @param {*} event 数据源
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private onChartClick(event: any) {
    if (!event || !event.name) {
      return;
    }
    const data: any = event.data;
    Object.assign(data, { _chartName: event.seriesId });
    this.c.selections = [data];
    this.c.ctrlEvent(MobChartEvents.SELECT_CHANGE, this.c.selections);
  }

  /**
   * @description 处理图表参数
   * @private
   * @return {*}  {IParam}
   * @memberof MobChartCtrlController
   */
  private handleChartOPtion(): IParam {
    const _chartOption: any = Util.deepCopy(this.c.chartOption);
    if (Object.keys(this.c.seriesModel).length > 0) {
      const tempDataSourceMap: Map<string, any> = new Map();
      for (let i = 0; i < Object.keys(this.c.seriesModel).length; i++) {
        Object.values(this.c.seriesModel).forEach((seriesvalue: any) => {
          if (seriesvalue.seriesIndex === i) {
            tempDataSourceMap.set(seriesvalue.name, seriesvalue.data);
          }
        });
      }
      if (tempDataSourceMap.size > 0) {
        tempDataSourceMap.forEach((item: any) => {
          _chartOption.dataset.push({ source: item });
        });
      }
      Object.keys(this.c.seriesModel).forEach((seriesName: string) => {
        if (_chartOption && _chartOption.series.length > 0) {
          _chartOption.series.forEach((item: any) => {
            if (this.c.seriesModel[seriesName].ecxObject && Object.is(seriesName, item.id)) {
              item = Util.deepObjectMerge(item, this.c.seriesModel[seriesName].ecxObject);
            }
            if (
              this.c.seriesModel[seriesName].baseOption &&
              Object.keys(this.c.seriesModel[seriesName].baseOption).length > 0 &&
              Object.is(seriesName, item.id)
            ) {
              item = Util.deepObjectMerge(item, this.c.seriesModel[seriesName].baseOption);
            }
            if (this.c.seriesModel[seriesName].ecObject && Object.is(seriesName, item.id)) {
              item = Util.deepObjectMerge(item, this.c.seriesModel[seriesName].ecObject);
            }
          });
        }
        //设置多序列
        const tempSeries: any = this.c.seriesModel[seriesName];
        const returnIndex: number = _chartOption.series.findIndex((item: any) => {
          return Object.is(item.id, seriesName);
        });
        // 仪表盘和雷达图数据特殊处理
        const source = _chartOption.dataset[0].source;
        const maxValue: number = this.calcSourceMaxValue(source);
        if (tempSeries && Object.is(tempSeries.type, 'gauge')) {
          _chartOption.series.splice(returnIndex, 1);
          const temSeries = {
            type: 'gauge',
            title: {
              fontSize: 14,
            },
            progress: {
              show: true,
              overlap: false,
              roundCap: true,
            },
            max: maxValue,
            detail: {
              width: 40,
              height: 14,
              fontSize: 14,
              color: '#fff',
              backgroundColor: 'auto',
              borderRadius: 3,
              formatter: '{value}',
            },
            data: this.transformToChartSeriesData(tempSeries, source, 'gauge'),
          };
          _chartOption.series.push(temSeries);
        } else if (tempSeries && Object.is(tempSeries.type, 'radar')) {
          if (_chartOption.radar.indicator?.length > 0) {
            _chartOption.radar.indicator?.forEach((item: any) => {
              item.max = item.max ? item.max : maxValue;
            });
          } else {
            const indicator: any[] = [];
            source.forEach((sourceItem: any) => {
              const item: any = {
                name: sourceItem[tempSeries.categorField],
                max: maxValue,
              };
              indicator.push(item);
            });
            Object.assign(_chartOption, { radar: { indicator } });
          }
          _chartOption.series[returnIndex].data = this.transformToChartSeriesData(
            tempSeries,
            source,
            'radar',
            _chartOption.radar.indicator,
          );
        } else if (tempSeries && tempSeries.seriesIdField && tempSeries.seriesValues.length > 0) {
          const series = _chartOption.series[returnIndex];
          _chartOption.series.splice(returnIndex, 1);
          delete series.id;
          tempSeries.seriesValues.forEach((seriesvalueItem: any) => {
            const tempSeriesTemp: any = Util.deepCopy(tempSeries.seriesTemp);
            Object.assign(tempSeriesTemp, series);
            tempSeriesTemp.name = tempSeries.seriesMap[seriesvalueItem];
            tempSeriesTemp.datasetIndex = tempSeries.seriesIndex;
            tempSeriesTemp.encode = { x: tempSeries.categorField, y: `${seriesvalueItem}` };
            _chartOption.series.push(tempSeriesTemp);
          });
        }
      });
    }
    if (Object.keys(this.c.chartBaseOPtion).length > 0) {
      Object.assign(_chartOption, this.c.chartBaseOPtion);
    }
    if (Object.keys(this.c.chartUserParams).length > 0) {
      Object.assign(_chartOption, this.c.chartUserParams);
    }
    return _chartOption;
  }

  /**
   * @description 实体数据集转化为图表数据集
   *  1.获取图表所有代码表值
   *  2.查询集合映射图表数据集
   *  3.补全图表数据集
   *  4.图表数据集分组求和
   *  5.排序图表数据集
   * @private
   * @param {*} data 实体数据集
   * @param {Function} callback 回调
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private async transformToBasicChartSetData(data: any, callback: Function) {
    if (!data || !Array.isArray(data) || data.length === 0) {
      this.c.isNoData = true;
      if (this.c.myChart) {
        this.c.myChart.dispose();
        this.c.myChart = undefined;
      }
      return;
    }
    this.c.isNoData = false;
    //获取代码表值
    const allCodeList: any = await this.getChartAllCodeList();
    if (Object.values(this.c.seriesModel).length > 0) {
      Object.values(this.c.seriesModel).forEach((singleSeries: any, index: number) => {
        // 值属性为srfcount设置{srfcount:1}到data
        const valueField = singleSeries.dataSetFields.find((datasetField: any) => {
          return datasetField.name === singleSeries.valueField;
        });
        if (valueField && valueField.name && Object.is(valueField.name, 'srfcount')) {
          data.forEach((singleData: any) => {
            Object.assign(singleData, { srfcount: 1 });
          });
        }
        // 分组属性
        const groupField = singleSeries.dataSetFields.find((datasetField: any) => {
          return datasetField.name === singleSeries.categorField;
        });
        const tempChartSetData: Array<any> = [];
        let tempSeriesValues: Map<string, any> = new Map();
        data.forEach((item: any) => {
          const tempChartSetDataItem: any = {};
          // 序列属性不存在
          if (!singleSeries.seriesIdField) {
            Object.assign(tempChartSetDataItem, { name: singleSeries.name });
            if (singleSeries.dataSetFields && singleSeries.dataSetFields.length > 0) {
              singleSeries.dataSetFields.forEach((singleDataSetField: any) => {
                this.handleSingleDataSetField(item, singleDataSetField, allCodeList, tempChartSetDataItem, groupField);
              });
            }
          } else {
            // 序列属性存在时
            // 序列代码表存在时,翻译tempSeriesValues的键值对
            if (singleSeries.seriesCodeList) {
              const seriesCodeList: Map<string, any> = allCodeList.get(singleSeries.seriesCodeList.tag);
              const tempSeriesValueItem = tempSeriesValues.get(seriesCodeList.get(item[singleSeries.seriesIdField]));
              if (!tempSeriesValueItem) {
                tempSeriesValues.set(
                  seriesCodeList.get(item[singleSeries.seriesIdField]),
                  seriesCodeList.get(item[singleSeries.seriesNameField]),
                );
              }
            } else {
              const tempSeriesValueItem = tempSeriesValues.get(item[singleSeries.seriesIdField]);
              if (!tempSeriesValueItem) {
                tempSeriesValues.set(item[singleSeries.seriesIdField], item[singleSeries.seriesNameField]);
              }
            }
            Object.assign(tempChartSetDataItem, { name: item[singleSeries.seriesIdField] });
            if (singleSeries.dataSetFields && singleSeries.dataSetFields.length > 0) {
              singleSeries.dataSetFields.forEach((singleDataSetField: any) => {
                this.handleSingleDataSetField(item, singleDataSetField, allCodeList, tempChartSetDataItem, groupField);
              });
            }
          }
          tempChartSetData.push(tempChartSetDataItem);
        });
        // 补全数据集合
        this.completeDataSet(tempChartSetData, singleSeries, allCodeList);
        // 序列代码表存在时,补全序列
        if (singleSeries.seriesCodeList) {
          const seriesCodeList: Map<string, any> = allCodeList.get(singleSeries.seriesCodeList.tag);
          tempSeriesValues = new Map();
          seriesCodeList.forEach((item: any) => {
            tempSeriesValues.set(item, item);
          });
        }
        singleSeries.seriesValues = [...tempSeriesValues.keys()];
        const tempSeriesMapObj: any = {};
        tempSeriesValues.forEach((value: any, key: any) => {
          tempSeriesMapObj[key] = value;
        });
        singleSeries.seriesMap = tempSeriesMapObj;
        const callbackFunction: any = index === Object.values(this.c.seriesModel).length - 1 ? callback : null;
        this.transformToChartSeriesDataSet(tempChartSetData, singleSeries, callbackFunction, allCodeList);
      });
    }
  }

  /**
   * @description 构建图表序列数据集合
   *  1.分组求和
   *  2.排序求和数组
   * @private
   * @param {*} data 传入数据
   * @param {*} item 单个序列
   * @param {Function} callback 回调
   * @param {*} allCodeList 所有代码表
   * @memberof MobChartCtrlController
   */
  private transformToChartSeriesDataSet(data: any, item: any, callback: Function, allCodeList: any): void {
    if (item.seriesIdField) {
      // 多序列
      const groupField = item.dataSetFields.filter((datasetField: any) => {
        return datasetField.name === item.categorField;
      });
      const tempGroupField: Array<any> = groupField.map((item: any) => {
        return item.name;
      });
      const seriesField = item.dataSetFields.filter((datasetField: any) => {
        return datasetField.name === item.seriesIdField;
      });
      const tempSeriesField: Array<any> = seriesField.map((item: any) => {
        return item.name;
      });
      const valueField = item.dataSetFields.filter((datasetField: any) => {
        return datasetField.name === item.valueField;
      });
      const tempValueField: Array<any> = valueField.map((item: any) => {
        return item.name;
      });
      item.data = this.groupAndAdd(
        tempGroupField,
        tempSeriesField,
        tempValueField,
        data,
        item,
        groupField,
        allCodeList,
      );
    } else {
      //单序列
      const groupField = item.dataSetFields.filter((datasetField: any) => {
        return datasetField.name === item.categorField;
      });
      const tempGroupField: Array<any> = groupField.map((item: any) => {
        return item.name;
      });
      const valueField = item.dataSetFields.filter((datasetField: any) => {
        return datasetField.name === item.valueField;
      });
      const tempValueField: Array<any> = valueField.map((item: any) => {
        return item.name;
      });
      item.data = this.groupAndAdd(tempGroupField, [], tempValueField, data, item, groupField, allCodeList);
    }
    if (callback && callback instanceof Function) {
      callback(allCodeList);
    }
  }

  /**
   * @description 分组和求和
   * @private
   * @param {Array<any>} groupField 分组属性
   * @param {Array<any>} seriesField 序列
   * @param {Array<any>} valueField 值属性
   * @param {*} data 传入数据
   * @param {*} item 项数据
   * @param {*} groupFieldModel 分组属性模型
   * @param {*} allCodeList 所有代码表
   * @return {*} {IParam[]}
   * @memberof MobChartCtrlController
   */
  private groupAndAdd(
    groupField: Array<any>,
    seriesField: Array<any>,
    valueField: Array<any>,
    data: any,
    item: any,
    groupFieldModel: any,
    allCodeList: any,
  ): IParam[] {
    const tempMap: Map<string, any> = new Map();
    const groupMode: string = groupFieldModel[0].groupMode;
    let groupKeyStr: string = '';
    data.forEach((item: any) => {
      const tempGroupField: string = groupField[0];
      groupKeyStr = item[tempGroupField];
      const tempMapItem: any = tempMap.get(groupKeyStr);
      if (tempMapItem) {
        tempMapItem.push(item);
        tempMap.set(groupKeyStr, tempMapItem);
      } else {
        tempMap.set(groupKeyStr, [item]);
      }
    });
    // 处理多序列
    if (seriesField.length > 0 && tempMap.size > 0) {
      const tempSeriesField: string = seriesField[0];
      tempMap.forEach((item: any, key: string) => {
        const tempItemMap: Map<string, any> = new Map();
        item.forEach((singleItem: any) => {
          const seriesValueArray: any = tempItemMap.get(singleItem[tempSeriesField]);
          if (seriesValueArray) {
            seriesValueArray.push(singleItem);
            tempItemMap.set(singleItem[tempSeriesField], seriesValueArray);
          } else {
            tempItemMap.set(singleItem[tempSeriesField], [singleItem]);
          }
        });
        tempMap.set(key, tempItemMap);
      });
    }
    let returnArray: Array<any> = [];
    if (seriesField.length == 0) {
      //单序列
      tempMap.forEach((tempItem: any) => {
        if (tempItem.length > 0) {
          const curObject: any = {};
          const valueResult: any = {};
          let categorResult: any;
          tempItem.forEach((singleItem: any) => {
            categorResult = singleItem[groupField[0]];
            valueResult[valueField[0]] = valueResult[valueField[0]]
              ? valueResult[valueField[0]] + singleItem[valueField[0]]
              : singleItem[valueField[0]];
            item.dataSetFields.forEach((dataSetField: any) => {
              // 只读不合并数据（扩展值属性4）
              if (dataSetField.isReadOnly) {
                valueResult[dataSetField.name] = singleItem[dataSetField.name];
              } else {
                if (!Object.is(dataSetField.name, groupField[0]) && !Object.is(dataSetField.name, valueField[0])) {
                  valueResult[dataSetField.name] = valueResult[dataSetField.name]
                    ? valueResult[dataSetField.name] + singleItem[dataSetField.name]
                    : singleItem[dataSetField.name];
                }
              }
            });
          });
          Object.defineProperty(curObject, groupField[0], {
            value: categorResult,
            writable: true,
            enumerable: true,
            configurable: true,
          });
          for (const value in valueResult) {
            Object.defineProperty(curObject, value, {
              value: valueResult[value],
              writable: true,
              enumerable: true,
              configurable: true,
            });
          }
          returnArray.push(curObject);
        }
      });
    } else {
      // 多序列
      const seriesValuesArray: Array<any> = item.seriesValues;
      tempMap.forEach((groupItem: any, groupKey: string) => {
        //求和
        const curObject: any = {};
        Object.defineProperty(curObject, groupField[0], {
          value: groupKey,
          writable: true,
          enumerable: true,
          configurable: true,
        });
        seriesValuesArray.forEach((seriesValueItem: any) => {
          Object.defineProperty(curObject, seriesValueItem, {
            value: 0,
            writable: true,
            enumerable: true,
            configurable: true,
          });
        });
        groupItem.forEach((seriesItem: any, seriesKey: string) => {
          let seriesNum: number = 0;
          seriesItem.forEach((dataItem: any) => {
            seriesNum += dataItem[valueField[0]];
          });
          curObject[seriesKey] = seriesNum;
        });
        returnArray.push(curObject);
      });
    }
    // 补全空白分类
    if (returnArray.length > 0) {
      const emptyText =
        groupFieldModel[0] && groupFieldModel[0].codeList ? groupFieldModel[0].codeList.emptytext : '未定义';
      returnArray.forEach((item: any) => {
        if (!item[groupField[0]]) {
          item[groupField[0]] = emptyText;
        }
      });
    }
    returnArray = this.sortReturnArray(returnArray, groupFieldModel, allCodeList);
    // 雷达图数据格式处理
    if (Object.is(item.type, 'radar') && returnArray.length > 0) {
      const tempReturnArray: Array<any> = [];
      const seriesValues: Array<any> = item.seriesValues;
      if (seriesValues && seriesValues.length > 0) {
        seriesValues.forEach((singleSeriesName: any) => {
          const singleSeriesObj: any = {};
          returnArray.forEach((item: any) => {
            Object.assign(singleSeriesObj, { [item[groupField[0]]]: item[singleSeriesName] });
          });
          Object.assign(singleSeriesObj, { type: singleSeriesName });
          tempReturnArray.push(singleSeriesObj);
        });
      }
      returnArray = tempReturnArray;
    }
    return returnArray;
  }

  /**
   * @description 排序数组
   * @private
   * @param {Array<any>} arr 传入数组
   * @param {*} groupField 分组属性
   * @param {*} allCodeList 所有代码表
   * @return {*}  {IParam[]}
   * @memberof MobChartCtrlController
   */
  private sortReturnArray(arr: Array<any>, groupField: any, allCodeList: any): IParam[] {
    let returnArray: Array<any> = [];
    // 分组属性有代码表的情况(最后执行)
    if (groupField[0].codelist) {
      const curCodeList: Map<number, any> = allCodeList.get(groupField[0].codelist.codeName);
      curCodeList.forEach((codelist: any) => {
        arr.forEach((item: any) => {
          if (Object.is(item[groupField[0].name], codelist)) {
            returnArray.push(item);
            item.hasused = true;
          }
        });
      });
      arr.forEach((item: any, index: number) => {
        if (!item.hasused) {
          returnArray.push(item);
        }
      });
      returnArray.forEach((item: any) => {
        delete item.hasused;
      });
    } else {
      // 分组为年份
      if (Object.is(groupField[0].groupMode, 'YEAR')) {
        returnArray = arr.sort((a: any, b: any) => {
          return Number(a[groupField[0].name]) - Number(b[groupField[0].name]);
        });
      } else if (Object.is(groupField[0].groupMode, 'QUARTER')) {
        returnArray = this.handleSortGroupData(arr, groupField, '季度' as string);
      } else if (Object.is(groupField[0].groupMode, 'MONTH')) {
        returnArray = this.handleSortGroupData(arr, groupField, '月' as string);
      } else if (Object.is(groupField[0].groupMode, 'YEARWEEK')) {
        returnArray = this.handleSortGroupData(arr, groupField, '周' as string);
      } else if (Object.is(groupField[0].groupMode, 'DAY')) {
        returnArray = arr.sort((a: any, b: any) => {
          return moment(a[groupField[0].name]).unix() - moment(b[groupField[0].name]).unix();
        });
      } else {
        const groupFieldName: string = groupField[0].name;
        let isConvert: boolean = true;
        arr.forEach((item: any) => {
          if (isNaN(item[groupFieldName])) {
            isConvert = false;
          }
        });
        if (isConvert) {
          returnArray = arr.sort((a: any, b: any) => {
            return a[groupFieldName] - b[groupFieldName];
          });
        } else {
          returnArray = arr;
        }
      }
    }
    return returnArray;
  }

  /**
   * @description 排序分组模式下的数据
   * @private
   * @param {Array<any>} arr 传入数据
   * @param {*} groupField 分组属性
   * @param {string} label label标签
   * @return {*}  {IParam[]}
   * @memberof MobChartCtrlController
   */
  private handleSortGroupData(arr: Array<any>, groupField: any, label: string): IParam[] {
    arr.forEach((item: any) => {
      const sortFieldValue: Array<any> = item[groupField[0].name].split('-');
      Object.assign(item, { sortField: Number(sortFieldValue[0]) * 10000 + Number(sortFieldValue[1]) });
      //  分组为月份时，月份+1
      if (Object.is(label, '月')) {
        item[groupField[0].name] = sortFieldValue[0] + ('年' as string) + (Number(sortFieldValue[1]) + 1) + label;
      } else {
        item[groupField[0].name] = sortFieldValue[0] + ('年' as string) + sortFieldValue[1] + label;
      }
    });
    arr.sort((a: any, b: any) => {
      return Number(a.sortField) - Number(b.sortField);
    });
    arr.forEach((item: any) => {
      delete item.sortField;
    });
    return arr;
  }

  /**
   * @description 补全数据集
   * @private
   * @param {*} data 传入数据
   * @param {*} item 单个序列
   * @param {*} allCodeList 所有的代码表
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private completeDataSet(data: any, item: any, allCodeList: any) {
    // 分组属性
    const groupField = item.dataSetFields.find((datasetField: any) => {
      return datasetField.name === item.categorField;
    });
    if (!groupField || Object.is(groupField.groupMode, '')) {
      return;
    }
    //分组模式为代码表（补值）
    if (Object.is(groupField.groupMode, 'CODELIST')) {
      this.completeCodeList(data, item, allCodeList);
    }
    //分组模式为年/季度/月份（最大值，最小值，分组，补值）
    if (
      Object.is(groupField.groupMode, 'YEAR') ||
      Object.is(groupField.groupMode, 'QUARTER') ||
      Object.is(groupField.groupMode, 'MONTH') ||
      Object.is(groupField.groupMode, 'YEARWEEK') ||
      Object.is(groupField.groupMode, 'DAY')
    ) {
      this.handleTimeData(data, item, allCodeList, groupField);
    }
  }

  /**
   * @description 获取最大值最小值
   * @private
   * @param {Array<any>} tempTimeArray 传入数组
   * @return {*} {IParam[]}
   * @memberof MobChartCtrlController
   */
  private getRangeData(tempTimeArray: Array<any>): IParam[] {
    tempTimeArray.forEach((item: any) => {
      const tempParams: Array<any> = item._i.split('-');
      item.sortField = Number(tempParams[0] + tempParams[1]);
    });
    tempTimeArray.sort((a: any, b: any) => {
      return Number(a.sortField) - Number(b.sortField);
    });
    tempTimeArray.forEach((item: any) => {
      delete item.sortField;
    });
    return tempTimeArray;
  }

  /**
   * @description 补全时间类型数据集
   * @private
   * @param {*} data 传入数据
   * @param {*} item 单个序列
   * @param {*} allCodeList 所有的代码表
   * @param {*} groupField 分组属性
   * @memberof MobChartCtrlController
   */
  private handleTimeData(data: any, item: any, allCodeList: any, groupField: any): void {
    const valueField = item.dataSetFields.find((datasetField: any) => {
      return datasetField.name === item.valueField;
    });
    const groupMode: string = groupField.groupMode;
    // 排序数据，找到最大值、最小值
    let tempTimeArray: Array<any> = [];
    if (data && data.length > 0) {
      data.forEach((dataItem: any) => {
        // 判断时间类型是否为空，为空不处理
        if (dataItem[groupField.name]) {
          tempTimeArray.push(moment(dataItem[groupField.name]));
        }
      });
    }
    let maxTime: any;
    let minTime: any;
    if (Object.is(groupMode, 'YEAR') || Object.is(groupMode, 'DAY')) {
      maxTime = moment.max(tempTimeArray);
      minTime = moment.min(tempTimeArray);
    }
    if (Object.is(groupMode, 'QUARTER')) {
      tempTimeArray = this.getRangeData(tempTimeArray);
      minTime = moment().year(tempTimeArray[0]._i.split('-')[0]).quarters(tempTimeArray[0]._i.split('-')[1]);
      maxTime = moment()
        .year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
        .quarters(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
    }
    if (Object.is(groupMode, 'MONTH')) {
      tempTimeArray = this.getRangeData(tempTimeArray);
      minTime = moment().year(tempTimeArray[0]._i.split('-')[0]).month(tempTimeArray[0]._i.split('-')[1]);
      maxTime = moment()
        .year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
        .month(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
    }
    if (Object.is(groupMode, 'YEARWEEK')) {
      tempTimeArray = this.getRangeData(tempTimeArray);
      minTime = moment().year(tempTimeArray[0]._i.split('-')[0]).week(tempTimeArray[0]._i.split('-')[1]);
      maxTime = moment()
        .year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
        .week(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
    }
    const timeFragmentArray: Array<any> = [];
    const tempGrounpData: Map<string, any> = new Map();
    // 时间分段
    //groupMode为"YEAR"
    if (Object.is(groupMode, 'YEAR')) {
      let curTime: any = minTime;
      while (curTime) {
        if (curTime.isSameOrBefore(maxTime)) {
          const tempcurTime: any = curTime.clone();
          timeFragmentArray.push(tempcurTime.year().toString());
          curTime = tempcurTime.clone().add(1, 'years');
        } else {
          curTime = null;
        }
      }
    }
    //groupMode为"QUARTER"
    if (Object.is(groupMode, 'QUARTER')) {
      let curTime: any = minTime;
      while (curTime) {
        if (curTime.isSameOrBefore(maxTime)) {
          const tempcurTime: any = curTime.clone();
          timeFragmentArray.push(tempcurTime.year().toString() + '-' + tempcurTime.quarter().toString());
          curTime = tempcurTime.clone().add(1, 'quarters');
        } else {
          curTime = null;
        }
      }
    }
    //groupMode为"MONTH"
    if (Object.is(groupMode, 'MONTH')) {
      let curTime: any = minTime;
      while (curTime) {
        if (curTime.isSameOrBefore(maxTime)) {
          const tempcurTime: any = curTime.clone();
          timeFragmentArray.push(tempcurTime.year().toString() + '-' + tempcurTime.month().toString());
          curTime = tempcurTime.clone().add(1, 'months');
        } else {
          curTime = null;
        }
      }
    }
    //groupMode为"YEARWEEK"
    if (Object.is(groupMode, 'YEARWEEK')) {
      let curTime: any = minTime;
      while (curTime) {
        if (curTime.isSameOrBefore(maxTime)) {
          const tempcurTime: any = curTime.clone();
          timeFragmentArray.push(tempcurTime.year().toString() + '-' + tempcurTime.week().toString());
          curTime = tempcurTime.clone().add(1, 'weeks');
        } else {
          curTime = null;
        }
      }
    }
    //groupMode为"DAY"
    if (Object.is(groupMode, 'DAY')) {
      let curTime: any = minTime;
      while (curTime) {
        if (curTime.isSameOrBefore(maxTime)) {
          const tempcurTime: any = curTime.clone();
          timeFragmentArray.push(tempcurTime.format('YYYY-MM-DD'));
          curTime = tempcurTime.clone().add(1, 'days');
        } else {
          curTime = null;
        }
      }
    }
    data.forEach((item: any) => {
      const tempKeyStr: string = item[groupField.name];
      const tempGrounpItem: any = tempGrounpData.get(tempKeyStr);
      if (!tempGrounpItem) {
        tempGrounpData.set(tempKeyStr, item);
      }
    });
    timeFragmentArray.forEach((timeFragment: any) => {
      if (!tempGrounpData.get(timeFragment)) {
        const copyTemp: any = Util.deepCopy(data[0]);
        const curObj: any = {};
        curObj[groupField.name] = timeFragment;
        curObj[valueField.name] = 0;
        Object.assign(copyTemp, curObj);
        data.push(copyTemp);
      }
    });
  }

  /**
   * @description 补全代码表
   * @private
   * @param {*} data 传入数据
   * @param {*} item 单个序列
   * @param {*} allCodeList 所有的代码表
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private completeCodeList(data: any, item: any, allCodeList: any) {
    const groupField = item.dataSetFields.find((datasetField: any) => {
      return datasetField.name === item.categorField;
    });
    if (!groupField.codelist) {
      return;
    }
    const valueField = item.dataSetFields.find((datasetField: any) => {
      return datasetField.name === item.valueField;
    });
    const curCodeList: Map<number, any> = allCodeList.get(groupField.codelist.codeName);
    // 对分类实现分组
    const tempGrounpData: Map<string, any> = new Map();
    data.forEach((item: any) => {
      const tempGrounpItem: any = tempGrounpData.get(item[groupField.name + '_srfvalue']);
      if (!tempGrounpItem) {
        tempGrounpData.set(item[groupField.name + '_srfvalue'], item);
      }
    });
    if (curCodeList.size !== tempGrounpData.size) {
      curCodeList.forEach((text: any, value: any) => {
        if (!tempGrounpData.get(value)) {
          const copyTemp: any = Util.deepCopy(data[0]);
          const curObj: any = {};
          curObj[groupField.name + '_srfvalue'] = value;
          curObj[groupField.name] = text;
          curObj[valueField.name] = 0;
          Object.assign(copyTemp, curObj);
          data.push(copyTemp);
        }
      });
    }
  }

  /**
   * @description 处理单个属性
   * @private
   * @param {*} input 输入值
   * @param {*} field 属性值
   * @param {*} allCodeList 所有代码表
   * @param {*} result 结果值
   * @param {*} groupField 分组属性
   * @memberof MobChartCtrlController
   */
  private handleSingleDataSetField(input: any, field: any, allCodeList: any, result: any, groupField: any): void {
    const tempFieldObj: any = {};
    //存在代码表的情况(自动转化值)
    if (field.codelist) {
      //获取代码表
      const curCodeList: Map<number, any> = allCodeList.get(field.codelist.codeName);
      tempFieldObj[field.name] = curCodeList.get(input[field.name]);
      tempFieldObj[field.name + '_srfvalue'] = input[field.name];
    } else {
      // 不存在代码表的情况
      if (groupField && Object.is(groupField.name, field.name)) {
        if (Object.is(groupField.groupMode, 'YEAR')) {
          tempFieldObj[field.name] = moment(input[field.name]).year().toString();
        } else if (Object.is(groupField.groupMode, 'QUARTER')) {
          tempFieldObj[field.name] =
            moment(input[field.name]).year().toString() + '-' + moment(input[field.name]).quarters().toString();
        } else if (Object.is(groupField.groupMode, 'MONTH')) {
          tempFieldObj[field.name] =
            moment(input[field.name]).year().toString() + '-' + moment(input[field.name]).month().toString();
        } else if (Object.is(groupField.groupMode, 'YEARWEEK')) {
          tempFieldObj[field.name] =
            moment(input[field.name]).year().toString() + '-' + moment(input[field.name]).week().toString();
        } else if (Object.is(groupField.groupMode, 'DAY')) {
          tempFieldObj[field.name] = moment(input[field.name]).format('YYYY-MM-DD');
        } else {
          tempFieldObj[field.name] = input[field.name];
        }
      } else {
        tempFieldObj[field.name] = input[field.name];
      }
    }
    Object.assign(result, tempFieldObj);
  }

  /**
   * @description 获取图表所需代码表
   * @private
   * @return {*}  {Promise<IParam>}
   * @memberof MobChartCtrlController
   */
  private getChartAllCodeList(): Promise<IParam> {
    return new Promise((resolve: any, reject: any) => {
      const codeListMap: Map<string, any> = new Map();
      if (Object.values(this.c.seriesModel).length > 0) {
        let tempFlag: boolean = true;
        Object.values(this.c.seriesModel).forEach((singleSeries: any) => {
          if (singleSeries.dataSetFields && singleSeries.dataSetFields.length > 0) {
            const promiseArray: Array<any> = [];
            const promiseKeyArray: Array<any> = [];
            singleSeries.dataSetFields.forEach((singleDataSetField: any, index: any) => {
              if (singleDataSetField.codelist) {
                tempFlag = false;
                if (!codeListMap.get(singleDataSetField.codelist.codeName)) {
                  promiseArray.push(this.getCodeList(singleDataSetField.codelist));
                  promiseKeyArray.push(singleDataSetField.codelist.codeName);
                  Promise.all(promiseArray).then((result: any) => {
                    if (result && result.length > 0) {
                      result.forEach((codeList: any) => {
                        const tempCodeListMap: Map<number, any> = new Map();
                        if (codeList.length > 0) {
                          codeList.forEach((codeListItem: any) => {
                            tempCodeListMap.set(codeListItem.value, codeListItem.text);
                          });
                        }
                        codeListMap.set(singleDataSetField.codelist.codeName, tempCodeListMap);
                      });
                      resolve(codeListMap);
                    }
                  });
                }
              }
            });
          }
        });
        if (tempFlag) {
          resolve(codeListMap);
        }
      } else {
        resolve(codeListMap);
      }
    });
  }

  /**
   * @description 获取代码表
   * @private
   * @param {*} codeListObject 代码表对象
   * @return {*}  {Promise<IParam>}
   * @memberof MobChartCtrlController
   */
  private getCodeList(codeListObject: any): Promise<IParam> {
    return new Promise((resolve: any, reject: any) => {
      App.getCodeListService()
        .getDataItems({
          tag: codeListObject.codeName,
          type: codeListObject.codeListType,
          navContext: this.c.context,
          navViewParam: this.c.viewParam,
        })
        .then((res: any) => {
          resolve(res);
        })
        .catch((error: any) => {
          LogUtil.error('代码表获取异常');
        });
    });
  }

  /**
   * @description 数组元素小写
   * @private
   * @param {*} arr 数组
   * @return {*} {IParam[]}
   * @memberof MobChartCtrlController
   */
  private arrayToLowerCase(arr: any): IParam[] {
    if (!arr || arr.length == 0) {
      return [];
    }
    for (let index = 0; index < arr.length; index++) {
      arr[index] = arr[index].toLowerCase();
    }
    return arr;
  }

  /**
   * @description 计算数据集最大数
   * @private
   * @param {any[]} source 传入数据
   * @return {*} {number}
   * @memberof MobChartCtrlController
   */
  private calcSourceMaxValue(source: any[]): number {
    const data: any[] = [];
    source.forEach((item: any) => {
      if (item.data) {
        data.push(item.data);
      } else {
        const itemData: any = [];
        for (const key in item) {
          if (!isNaN(item[key])) {
            itemData.push(item[key]);
          }
        }
        data.push(Math.max(...itemData));
      }
    });
    return Math.max(...data);
  }

  /**
   * @description 是否为数组字符串
   * @private
   * @param {string} str 字符串
   * @return {*}  {boolean}
   * @memberof MobChartCtrlController
   */
  private isArray(str: string): boolean {
    try {
      eval(str);
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * @description 是否为json字符串
   * @private
   * @param {*} str 字符串
   * @return {*}  {boolean}
   * @memberof MobChartCtrlController
   */
  private isJson(str: any): boolean {
    try {
      JSON.parse(str);
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * @description 解析字符串函数
   * @private
   * @param {*} data 传入数据
   * @return {*}
   * @memberof MobChartCtrlController
   */
  private deepJsonParseFun(data: any): any {
    switch (typeof data) {
      case 'string':
      case 'number':
      case 'boolean':
      case 'undefined':
      case 'function':
      case 'symbol':
        return data;
    }
    for (const key in data) {
      const item = data[key];
      let res: any;
      if (item.isFun && item.functionBody) {
        res = new Function(item.arg, item.functionBody);
      } else {
        res = this.deepJsonParseFun(item);
      }
      data[key] = res;
    }
    return data;
  }

  /**
   * @description 整合图表数据集data
   * @private
   * @param {any[]} source 传入数据
   * @param {string} series 序列
   * @param {any[]} [indicator] 雷达图参数
   * @return {*}
   * @memberof MobChartCtrlController
   */

  /**
   *
   * @description 整合图表数据集data
   * @private
   * @param {*} series 序列
   * @param {any[]} source 传入数据
   * @param {string} type 类型
   * @param {any[]} [indicator] 雷达图参数
   * @return {*}  {*}
   * @memberof AppMobChart
   */
  private transformToChartSeriesData(series: any, source: any[], type: string, indicator?: any[]): any {
    const seriesValueField = series.valueField?.toLowerCase();
    const seriesCatalogField = series.catalogField?.toLowerCase();
    if (Object.is(type, 'gauge')) {
      const seriesData: any[] = [];
      const offsetLength: number = 100 / (source.length - 1);
      source.forEach((sourceItem: any, index: number) => {
        const data = {
          name: sourceItem[seriesCatalogField],
          value: sourceItem[seriesValueField],
          title: {
            offsetCenter: [index * offsetLength - 50 + '%', '80%'],
          },
          detail: {
            offsetCenter: [index * offsetLength - 50 + '%', '95%'],
          },
        };
        seriesData.push(data);
      });
      return seriesData;
    } else if (Object.is(type, 'radar')) {
      if (!indicator || indicator.length == 0) {
        LogUtil.log('雷达图indicator不存在，无法转换数据集！');
        return;
      }
      const seriesData: any[] = [];
      source.forEach((sourceItem: any) => {
        const name = sourceItem.type;
        const data: any[] = [];
        indicator.forEach((item: any) => {
          data.push(sourceItem[item.name]);
        });
        seriesData.push({ name, value: data });
      });
      return seriesData;
    }
  }

  /**
   * @description 绘制图表
   * @return {*}
   * @memberof AppMobChart
   */
  render() {
    if (!this.controlIsLoaded.value) {
      return null;
    }
    const { width, height } = this.c.controlInstance;
    const chartControlstyle = {
      width: width ? `${width}px` : '100%',
      height: height ? `${height}px` : '100%',
    };
    return (
      <div class={{ ...this.classNames }} style={chartControlstyle}>
        {this.renderPullDownRefresh()}
        {this.c.isNoData ? this.renderNoData() : <div class='echarts' id={this.c.chartId}></div>}
      </div>
    );
  }
}
// 移动端图表部件
export const AppMobChartComponent = GenerateComponent(AppMobChart, Object.keys(new AppMobChartProps()));
